package com.cazadoresmadridejos;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import org.apache.log4j.Logger;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import es.cazadoresmadridejos.model.Access;
import es.cazadoresmadridejos.model.BaseEntity;


public class CodeGeneratorService {

	private VelocityEngine velocityEngine;
	private boolean hasCreateModify = false;
	private boolean hasProfile = false;
	private boolean hasList = false;
	private boolean hasManager = true;
	private boolean hasManagerImpl = true;
	private boolean hasDao = true;
	private boolean hasDaoImpl = true;
	private String basePath = 
			"src/main/java/";
	private String basePathJSP = 
			"src/main/webapp/WEB-INF/views";

	Class<? extends BaseEntity> clazz = Access.class;
	private String varClass =  String.valueOf(clazz.getSimpleName().toCharArray()[0]).toLowerCase() + clazz.getSimpleName().substring(1);
	private Logger logger = Logger.getLogger(this.getClass());

	public enum ClassType{
		Manager, ManagerImpl, Dao, DaoImpl, CreateModifyController, ProfileController, ListController, Validator, PropertyEditor
	}

	public static void main(String[] args) throws Throwable {

		CodeGeneratorService service = new CodeGeneratorService();
		service.generate();
	}


	public void generate() throws Throwable{

		String basePackage = "es/cazadoresmadridejos";

		String packageValidator= basePackage + "/beans/validator/"+ clazz.getSimpleName().toLowerCase() ;
		String packageController = basePackage + "/beans/controller/"+ clazz.getSimpleName().toLowerCase() ;
		String packageManager = basePackage + "/beans/manager/" + clazz.getSimpleName().toLowerCase() ;
		String packageManagerImpl = basePackage + "/beans/manager/" + clazz.getSimpleName().toLowerCase()+ "/impl";
		String packageDao = basePackage + "/beans/dao/"+ clazz.getSimpleName().toLowerCase();
		String packageDaoImpl = basePackage + "/beans/dao/" + clazz.getSimpleName().toLowerCase()+ "/impl";
		String packagePropertyEditor = basePackage + "/propertyeditor";
		
		String importValidationContainer= "es.cazadoresmadridejos.util.validation.ValidationContainer";
		


		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/codegeneration-service.xml");
		velocityEngine = context.getBean(VelocityEngine.class);

		VelocityContext velocityContext = new VelocityContext();

		//VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, "classpath:vm/test.vm", velocityContext);

		String managerImport = packageManager.replaceAll("/", ".") + "." +clazz.getSimpleName() + "Manager";
		String validatorImport  = basePackage.replaceAll("/", ".") + ".beans.validator." + clazz.getSimpleName().toLowerCase()+ "." + clazz.getSimpleName() + "Validator";
		String importPropertyEditor = (basePackage + "/propertyeditor/").replace("/", ".") + clazz.getSimpleName() + "PropertyEditor" ;
		
		if(hasManager){
			velocityContext.put("className", clazz.getName());
			velocityContext.put("simpleClassName", clazz.getSimpleName());
			generateTemplateByType(
					packageManager,
					velocityContext, ClassType.Manager);
		}
		if(hasManagerImpl){
			velocityContext.put("className", clazz.getName());
			velocityContext.put("managerImport", managerImport);
			velocityContext.put("simpleClassName", clazz.getSimpleName());
			velocityContext.put("varClass", String.valueOf(clazz.getSimpleName().toCharArray()[0]).toLowerCase() + clazz.getSimpleName().substring(1));
			generateTemplateByType(
					packageManagerImpl,
					velocityContext, ClassType.ManagerImpl);
		}
		if(hasDao){
			velocityContext.put("className", clazz.getName());
			velocityContext.put("simpleClassName", clazz.getSimpleName());
			generateTemplateByType(
					packageDao, 
					velocityContext, ClassType.Dao);
		}
		if(hasDaoImpl){
			velocityContext.put("className", clazz.getName());
			velocityContext.put("daoImport", packageDao.replaceAll("/", ".") + "." +clazz.getSimpleName() + "Dao");
			velocityContext.put("simpleClassName", clazz.getSimpleName());
			velocityContext.put("varClass", varClass);
			generateTemplateByType(
					packageDaoImpl, 
					velocityContext, ClassType.DaoImpl);
		}
		if(hasCreateModify){
			velocityContext.put("className", clazz.getName());
			velocityContext.put("managerImport", managerImport);
			velocityContext.put("validatorImport", validatorImport);
			velocityContext.put("simpleClassName", clazz.getSimpleName());
			velocityContext.put("validatorImport", validatorImport);
			velocityContext.put("importPropertyEditor", importPropertyEditor);
			velocityContext.put("varClass", varClass);
			velocityContext.put("importValidationContainer", importValidationContainer);
			generateTemplateByType(
					packageController, 
					velocityContext, ClassType.CreateModifyController);
			
			generateTemplateByType(
					packageValidator, 
					velocityContext, ClassType.Validator);
		}
		if(hasProfile){
			velocityContext.put("className", clazz.getName());
			velocityContext.put("propertyEditor", clazz.getSimpleName());
			velocityContext.put("varClass", varClass);
			velocityContext.put("importPropertyEditor", importPropertyEditor);
			velocityContext.put("importManager", managerImport);
			
			generateTemplateByType(
					packageController, 
					velocityContext, ClassType.ProfileController);
			
			generateTemplateByType(
					packagePropertyEditor, 
					velocityContext, ClassType.PropertyEditor);
		}
		if(hasList){
			velocityContext.put("className", clazz.getName());
			velocityContext.put("varClass", varClass);
			generateTemplateByType(
					packageController, 
					velocityContext, ClassType.ListController);
		}

	}


	private void generateTemplateByType(
			String argPackage, VelocityContext velocityContext, ClassType classType)
					throws IOException {
		logger.debug("Creando " + classType.name() + "...");
		FileWriter writer = null;
		try{
			String path = argPackage;
			String fileName = clazz.getSimpleName() + classType.toString() + ".java";

			logger.debug("Paquetería: " + path);
			logger.debug("Nombre del fichero: " + fileName);

			File baseDirectory = new File(basePath + path);
			if(!baseDirectory.exists()){
				logger.debug("Creando directorio " + baseDirectory.getAbsolutePath() );
				baseDirectory.mkdir();
				logger.debug("Creado directorio " + baseDirectory.getAbsolutePath() );
			}

			String finalPath = basePath + path +"/" + fileName;
			baseDirectory = new File(finalPath);

			logger.debug("Creando archivo final: " + baseDirectory.getAbsolutePath() + "...");
			baseDirectory.createNewFile();
			writer = new FileWriter(baseDirectory);
			logger.debug("Contexto: " + velocityContext.toString());
			velocityContext.put(
					"mainPackage", 
					path.replaceAll("/", "."));
			velocityEngine.mergeTemplate("vm/" + classType.toString()+".vm", "UTF-8", velocityContext, writer);
			
			if(classType.name().endsWith("Controller")){
				File file = new File(basePathJSP.toString().replace("Controller", "") + "/" + varClass + classType.name().replace("Controller", "") + ".jspx");
				if(!file.exists()){
					file.createNewFile();
				}
			}
		}catch(Exception e){
			logger.error("Error creando el archivo",e);
		}finally{
			writer.flush();
			writer.close();
		}
	}
}
